/**
 *
 */
package com.ruicar.afs.cloud.afscase.dispatch.service.impl;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.afscase.approvetask.entity.WorkProcessScheduleInfoTemp;
import com.ruicar.afs.cloud.afscase.approvetask.service.WorkProcessScheduleInfoTempService;
import com.ruicar.afs.cloud.afscase.common.utils.Const;
import com.ruicar.afs.cloud.afscase.dispatch.DispatchContext;
import com.ruicar.afs.cloud.afscase.dispatch.annotation.Dispatch;
import com.ruicar.afs.cloud.afscase.dispatch.enums.DispatchTypeEnum;
import com.ruicar.afs.cloud.afscase.dispatch.service.DispatchBaseServcie;
import com.ruicar.afs.cloud.afscase.infomanagement.entity.CaseBaseInfo;
import com.ruicar.afs.cloud.afscase.infomanagement.service.CaseBaseInfoService;
import com.ruicar.afs.cloud.afscase.processor.service.ApproveWorkflowService;
import com.ruicar.afs.cloud.afscase.processor.util.WorkflowTypeUtil;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.BusinessStateInEnum;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.WhetherEnum;
import com.ruicar.afs.cloud.common.rules.RuleHelper;
import com.ruicar.afs.cloud.common.rules.constants.RuleRunEnum;
import com.ruicar.afs.cloud.common.rules.dto.RuleRunResult;
import com.ruicar.afs.cloud.seats.entity.RegularValue;
import com.ruicar.afs.cloud.seats.service.RegularValueService;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.WorkFlowResponse;
import com.ruicar.afs.cloud.workflow.gwt.service.WorkflowService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 *<p>Description: </p>  
 * @author happysayhello
 * @date Jun 16, 2020 
 */
@Slf4j
@Service
@Dispatch(name = "启动信审审批流程", dependsOn = "dispatchTimeBeforService", group = DispatchTypeEnum.CREDIT)
public class DispatchStartService extends DispatchBaseServcie {
    @Autowired
    private RegularValueService valueService;

    @Autowired
    private WorkProcessScheduleInfoTempService workProcessScheduleInfoTempService;


    @Autowired
    private ApproveWorkflowService approveWorkflowService;

    @Autowired
    private WorkflowService workflowService;

    @Autowired
    private CaseBaseInfoService caseBaseInfoService;

    @Override
    public void process(DispatchContext context) throws Exception {

        List<CaseBaseInfo> caseInfoList = (List) (Optional.ofNullable(context.get(KEY)).orElse(new ArrayList()));
        if (caseInfoList.isEmpty()) {
            return;
        }
        // 优先级排序
        List<CaseBaseInfo> recycleCaseList = caseInfoList.stream().filter(caseInfo -> WhetherEnum.YES.getCode().equals(caseInfo.getFlowRecycleStatus())).collect(Collectors.toList());
        List<CaseBaseInfo> normalCaseList = caseInfoList.stream().filter(caseInfo -> !WhetherEnum.YES.getCode().equals(caseInfo.getFlowRecycleStatus())).collect(Collectors.toList());

        // 离岗回收案件
        List<CaseBaseInfo> list = recycleCaseList.stream().sorted(
                (first, second) -> Convert.toInt(second.getPriority(), -1).compareTo(Convert.toInt(first.getPriority(), -1))
        ).collect(Collectors.toList());

        // 常规案件
        normalCaseList = normalCaseList.stream().sorted(
                (first, second) -> Convert.toInt(second.getPriority(), -1).compareTo(Convert.toInt(first.getPriority(), -1))
        ).collect(Collectors.toList());

        list.addAll(normalCaseList);

        for (CaseBaseInfo caseInfo : list) {
            JSONObject jsonObject = (JSONObject) context.get(caseInfo.getId());
            RuleRunResult result = RuleHelper.runRule(jsonObject, "approveProcedure", false, RuleRunEnum.SERIAL);
            if (result.getHit()) {
                List<String> listNo = result.getResults().stream().map(s -> s.getRuleNo()).collect(Collectors.toList());
                if (listNo.isEmpty())
                    return;
                List<RegularValue> valueList = valueService.listByIds(listNo);
                if (valueList == null || valueList.isEmpty())
                    return;
                String[] value = valueList.stream().map(s -> {
                    String[] str = s.getValue().split("#");
                    return str;
                }).max(Comparator.comparing(s -> s[0])).get();
                String afsFlowKey = value[1];
                try {
                    log.info("流程匹配命中结果[{}],流程编号为[{}]", JSON.toJSONString(listNo), afsFlowKey);
                    if (flowBeforeCheck(caseInfo, BusinessStateInEnum.ALLOCATION)) {
                        log.info("流程发起：{}-{}", caseInfo.getApplyNo(), afsFlowKey);
                        WorkProcessScheduleInfoTemp info = createLocalWorkProcessor(caseInfo.getApplyNo(), value[1]);
                        approveWorkflowService.start(info);
                    } else if (flowBeforeCheck(caseInfo, BusinessStateInEnum.TASK_ASSIGN)
                            && WhetherEnum.YES.getCode().equals(caseInfo.getFlowParseFlag())) {
                        log.info("流程恢复：{}", caseInfo.getApplyNo());
                        processFlowException(caseInfo);
                    }
                }catch (Exception e){
                    log.error("分单失败:"+e.getMessage(),e);
                }
            }
        }
    }

    /**
    * @Description 待分配任务池中可能对案件进行指定处理人操作，此时业务状态可能已经改变
    * @Author Peng_Jinbo
    * @Date 2020/8/28 19:12
    */
    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
    public boolean flowBeforeCheck(CaseBaseInfo caseBaseInfo,BusinessStateInEnum businessStateInEnum){
        return caseBaseInfoService.count(
                Wrappers.<CaseBaseInfo>lambdaQuery()
                        .eq(CaseBaseInfo::getApplyNo,caseBaseInfo.getApplyNo())
                        .eq(CaseBaseInfo::getBusinessStateIn,AfsEnumUtil.key(businessStateInEnum))
        ) > 0;
    }

    /**
     * @Description 创建流程实例
     * @Author Peng_Jinbo
     * @Date 2020/6/17 14:11
     */
    public WorkProcessScheduleInfoTemp createLocalWorkProcessor(String applyNo, String afsFlowKey) {
        // 保存工作流实例
        WorkProcessScheduleInfoTemp info = new WorkProcessScheduleInfoTemp();
        info.setAfsFlowKey(afsFlowKey);
        info.setApplyNo(applyNo);
        info.setProcessName(WorkflowTypeUtil.getApproveTypeName(afsFlowKey));
        workProcessScheduleInfoTempService.saveWithNewTransactional(info);
        return info;
    }


    public void processFlowException(CaseBaseInfo caseInfo){
        WorkFlowResponse response = workflowService.resumeFlow(caseInfo.getFlowParseId(),caseInfo.getFlowParseExceptionId());
        if (!(Const.WORKFLOW_RESPONSE_SUCCESS == response.getSuccess())) {
            log.warn("流程恢复失败，stageId:{},exceptionId:{}.message:{}",caseInfo.getFlowParseId(),caseInfo.getFlowParseExceptionId(),response.getMessage());
        }

    }

}
